﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace SXFramWork.Core
{
    /// <summary>
    /// 文件读写操作
    /// </summary>
    public class FileHelper : IDisposable
    {
       
        private static IWebHostEnvironment _hostingEnvironment = new HttpContextAccessor().HttpContext.RequestServices.GetService(typeof(IWebHostEnvironment)) as IWebHostEnvironment;
        /// <summary>
        /// wwwroot目录 E:\SXFramWork\SXFramWork\SXFramWork.Web\wwwroot
        /// </summary>
        private static string _ContentRootPath = _hostingEnvironment.WebRootPath;

        //应用程序根目录 E:\SXFramWork\SXFramWork\SXFramWork.Web
        //private static string _ContentRootPath = _hostingEnvironment.ContentRootPath;

        /// <summary>
        /// 目录分隔符
        /// windows "\" OSX and Linux  "/"
        /// </summary>
        private static string DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString();


        private bool _alreadyDispose = false;

        public FileHelper()
        {
        }
        ~FileHelper()
        {
            Dispose();
        }
        protected virtual void Dispose(bool isDisposing)
        {
            if (_alreadyDispose) return;
            _alreadyDispose = true;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// 获取文件绝对路径
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        public static string MapPath(string path)
        {
            return Path.Combine(_ContentRootPath, path.TrimStart('~', '/').Replace("/", DirectorySeparatorChar));
        }
        #region 物理路径转虚拟路径
        public static string PhysicalToVirtual(string physicalPath)
        {
            return physicalPath.Replace(_ContentRootPath, "").Replace(DirectorySeparatorChar, "/");
        }
        #endregion


        #region 创建文件或目录
        /// <summary>
        /// 创建文件或目录
        /// </summary>
        /// <param name="path">路径</param>
        public static async Task Create(string path)
        {
            try
            {
                if (IsDirectory(MapPath(path)))
                   await Task.Run(()=>Directory.CreateDirectory(MapPath(path)));
                else
                   await Task.Run(()=> File.Create(MapPath(path)).Dispose());
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 删除文件或目录
        /// <summary>
        /// 删除文件目录
        /// </summary>
        /// <param name="path">路径</param>
        public static async Task Delete(string path)
        {
            try
            {
                if (IsExist(path))
                {
                    if (IsDirectory(MapPath(path)))
                       await Task.Run(()=> Directory.Delete(MapPath(path)));
                    else
                       await Task.Run(()=> File.Delete(MapPath(path)));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion
        /// <summary>
        /// 是否为目录或文件夹
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns></returns>
        public static bool IsDirectory(string path)
        {
            if (path.EndsWith(DirectorySeparatorChar))
                return true;
            else
                return false;
        }
        /// <summary>
        /// 检测指定路径是否存在
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns></returns>
        public static bool IsExist(string path)
        {
            return IsDirectory(MapPath(path)) ? Directory.Exists(MapPath(path)) : File.Exists(MapPath(path));
        }

        #region 不常用方法

        /// <summary>
        /// 获得指定文件夹下面的所有文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="staticFiles"></param>
        /// <returns></returns>
        public static List<FilesInfo> ResolveFileInfo(string path, string staticFiles = "/wwwroot")
        {
            var foldersPath = MapPath(path);
            var Files = new List<FilesInfo>();
            foreach (var fsi in new DirectoryInfo(foldersPath).GetFiles())
            {
                Files.Add(new FilesInfo()
                {
                    Name = fsi.Name,
                    FullName = fsi.FullName,
                    FileExt = fsi.Extension,
                    FileOriginalSize = fsi.Length,
                    FileSize = FileSizeTransf(fsi.Length),
                    FileIcon = FindFileIcon(fsi.Extension.Remove(0, 1)),
                    FileName = PhysicalToVirtual(fsi.FullName).Replace(staticFiles, ""),
                    FileStyle = IsImage(fsi.Extension.Remove(0, 1)) ? "images" :
                                IsDocument(fsi.Extension.Remove(0, 1)) ? "documents" :
                                IsVideos(fsi.Extension.Remove(0, 1)) ? "videos" :
                                IsMusics(fsi.Extension.Remove(0, 1)) ? "musics" : "others",
                    CreateDate = fsi.CreationTime,
                    LastWriteDate = fsi.LastWriteTime,
                    LastAccessDate = fsi.LastAccessTime
                });
            }
            return Files;
        }


        #region 文件大小转换
        /// <summary>
        ///  文件大小转为B、KB、MB、GB...
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public static string FileSizeTransf(long size)
        {
            String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "PB" };
            long mod = 1024;
            int i = 0;
            while (size > mod)
            {
                size /= mod;
                i++;
            }
            return size + units[i];

        }
        #endregion

        #region 文件图标
        public static string FindFileIcon(string fileExt)
        {
            if (IsImage(fileExt))
                return "fa fa-image";
            if (IsVideos(fileExt))
                return "fa fa-film";
            if (IsMusics(fileExt))
                return "fa fa-music";
            if (IsDocument(fileExt))
                switch (fileExt.ToLower())
                {
                    case ".xls":
                    case ".xlsx":
                        return "fa fa-file-excel-o";
                    case ".ppt":
                    case ".pptx":
                        return "fa fa-file-powerpoint-o";
                    case ".pdf":
                        return "fa fa-file-pdf-o";
                    case ".txt":
                        return "fa fa-file-text-o";
                    default:
                        return "fa fa-file-word-o";
                }
            if (fileExt.ToLower() == "zip" || fileExt.ToLower() == "rar")
                return "fa fa-file-zip-o";
            else
                return "fa fa-file";
        }
        #endregion

        #region 文件格式
        /// <summary>
        /// 是否可添加水印
        /// </summary>
        /// <param name="_fileExt">文件扩展名，不含“.”</param>
        /// <returns></returns>
        public static bool IsCanWater(string _fileExt)
        {
            var images = new List<string> { "jpg", "jpeg" };
            if (images.Contains(_fileExt.ToLower())) return true;
            return false;
        }
        /// <summary>
        /// 是否为图片
        /// </summary>
        /// <param name="_fileExt">文件扩展名，不含“.”</param>
        /// <returns></returns>
        public static bool IsImage(string _fileExt)
        {
            var images = new List<string> { "bmp", "gif", "jpg", "jpeg", "png" };
            if (images.Contains(_fileExt.ToLower())) return true;
            return false;
        }
        /// <summary>
        /// 是否为视频
        /// </summary>
        /// <param name="_fileExt">文件扩展名，不含“.”</param>
        /// <returns></returns>
        public static bool IsVideos(string _fileExt)
        {
            var videos = new List<string> { "rmvb", "mkv", "ts", "wma", "avi", "rm", "mp4", "flv", "mpeg", "mov", "3gp", "mpg" };
            if (videos.Contains(_fileExt.ToLower())) return true;
            return false;
        }
        /// <summary>
        /// 是否为音频
        /// </summary>
        /// <param name="_fileExt">文件扩展名，不含“.”</param>
        /// <returns></returns>
        public static bool IsMusics(string _fileExt)
        {
            var musics = new List<string> { "mp3", "wav" };
            if (musics.Contains(_fileExt.ToLower())) return true;
            return false;
        }
        /// <summary>
        /// 是否为文档
        /// </summary>
        /// <param name="_fileExt">文件扩展名，不含“.”</param>
        /// <returns></returns>
        public static bool IsDocument(string _fileExt)
        {
            var documents = new List<string> { "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf" };
            if (documents.Contains(_fileExt.ToLower())) return true;
            return false;
        }
        #endregion
        #endregion 
    }

    public class FilesInfo
    {
        /// <summary>
        /// 文件名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 文件物理路径
        /// </summary>
        public string FullName { get; set; }
        /// <summary>
        /// 扩展名
        /// </summary>
        public string FileExt { get; set; }
        /// <summary>
        /// 原始大小（字节）
        /// </summary>
        public long FileOriginalSize { get; set; }
        /// <summary>
        /// 文件大小
        /// </summary>
        public string FileSize { get; set; }
        /// <summary>
        /// 文件虚拟路径
        /// </summary>
        public string FileName { get; set; }
        /// <summary>
        /// 文件类型
        /// </summary>
        public string FileStyle { get; set; }
        /// <summary>
        /// 文件图标
        /// </summary>
        public string FileIcon { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateDate { get; set; }
        /// <summary>
        /// 最后修改时间
        /// </summary>
        public DateTime LastWriteDate { get; set; }
        /// <summary>
        /// 最后访问时间
        /// </summary>
        public DateTime LastAccessDate { get; set; }

    }
}
